#set( $symbol_pound = '#' )
#set( $symbol_dollar = '$' )
#set( $symbol_escape = '\' )
package ${package}.biz.pay.alipay;



import ${package}.biz.helper.HttpClientHelper;
import ${package}.biz.helper.HttpResult;
import ${package}.biz.pay.alipay.sign.RSA;
import org.apache.commons.codec.digest.DigestUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.*;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.*;

/**
 * Created by well on 15/3/12.
 */
public class AlipayHelper {

    private static final String ALIPAY_GATE_WAY = "https://mapi.alipay.com/gateway.do?";
    private static final String ALIPAY_GATE_WAY_NOTIFY_VERIFY = "https://mapi.alipay.com/gateway.do?service=notify_verify";
    private static final String DEFAULT_CHARSET = "utf-8";

    private static final Logger log = LoggerFactory.getLogger(AlipayHelper.class);

    public static String buildRequestWithSign(Map<String, String> paramMap, String sellerKey) {
        String queryString = createQueryString(paramMap);
        return sign(queryString, sellerKey);

    }

    private static Map<String, String> appendSign(Map<String, String> paramMap, String sellerKey) {
        Map<String, String> param = paramFilter(paramMap);
        String str = buildRequestWithSign(param, sellerKey);
        param.put("sign", str);
        param.put("sign_type", "MD5");
        return param;
    }

    public static String buildRequest(Map<String, String> paramMap, String sellerKey, String method, String buttonName) {
        Map<String, String> paramWithSign = appendSign(paramMap, sellerKey);
        List<String> paramList = new ArrayList<String>(paramWithSign.keySet());
        StringBuilder buff = new StringBuilder();
        buff.append("<form id=${symbol_escape}"alipaysubmit${symbol_escape}" name=${symbol_escape}"alipaysubmit${symbol_escape}" action=${symbol_escape}"" + ALIPAY_GATE_WAY + "_input_charset=utf-8${symbol_escape}" method=${symbol_escape}"" + method + "${symbol_escape}">");
        for (int i = 0; i < paramList.size(); i++) {
            String str1 = paramList.get(i);
            String str2 = paramWithSign.get(str1);
            buff.append("<input type=${symbol_escape}"hidden${symbol_escape}" name=${symbol_escape}"" + str1 + "${symbol_escape}" value=${symbol_escape}"" + str2 + "${symbol_escape}"/>");
        }
        buff.append("<input type=${symbol_escape}"submit${symbol_escape}" value=${symbol_escape}"" + buttonName + "${symbol_escape}" style=${symbol_escape}"display:none;${symbol_escape}"></form>");
        buff.append("<script>document.forms['alipaysubmit'].submit();</script>");
        return buff.toString();
    }


    public static Map<String, String> paramFilter(Map<String, String> paramMap) {
        HashMap hashMap = new HashMap();
        if ((paramMap == null) || (paramMap.size() <= 0)) {
            return hashMap;
        }
        Iterator<String> keyIterator = paramMap.keySet().iterator();
        while (keyIterator.hasNext()) {
            String str1 = keyIterator.next();
            String str2 = paramMap.get(str1);
            if ((str2 != null) && (!str2.equals("")) && (!str1.equalsIgnoreCase("sign")) && (!str1.equalsIgnoreCase("sign_type")))
                hashMap.put(str1, str2);
        }
        return hashMap;
    }

    public static String createQueryString(Map<String, String> paramMap) {
        List<String> paramList = new ArrayList<String>(paramMap.keySet());
        Collections.sort(paramList);
        StringBuilder buf = new StringBuilder();
        for (int i = 0; i < paramList.size(); i++) {
            String key = paramList.get(i);
            String val = paramMap.get(key);
            if (i == paramList.size() - 1) {
                buf.append(key).append("=").append(val);
            } else {
                buf.append(key).append("=").append(val).append("&");
            }
        }
        return buf.toString();
    }

    public static String sign(String queryString, String sellerKey) {
        queryString = queryString + sellerKey;
        return DigestUtils.md5Hex(getBytes(queryString));
    }



    private static byte[] getBytes(String queryString) {
        try {
            return queryString.getBytes(DEFAULT_CHARSET);
        } catch (UnsupportedEncodingException ex) {
        }
        throw new RuntimeException("MD5签名过程中出现错误,指定的编码集不对,您目前指定的编码集是:" + DEFAULT_CHARSET);
    }



    public static boolean verify(Map<String, String> paramMap, String partner, String sellerKey) {
        String str1 = "true";
        if (paramMap.get("notify_id") != null) {
            String notifyId = paramMap.get("notify_id");
            str1 = appendPartnerAndCheck(notifyId, partner);
            if(!str1.equals("true")){
                log.error("check notify error,alipay return:["+str1+"],notifyId:" + notifyId);
            }
        }
        String sign = "";
        if (paramMap.get("sign") != null) {
            sign = paramMap.get("sign");
        }
        boolean bool = appendCharset(paramMap, sign, sellerKey);
        return bool&& (str1.equals("true"));
    }

    private static boolean appendCharset(Map<String, String> paramMap, String sign, String sellerKey) {
        String signType = paramMap.get("sign_type");
        Map localMap = paramFilter(paramMap);
        String queryString = createQueryString(localMap);
        log.info("alipay check query string:" + queryString);
        boolean verify = verifySign(queryString, sign, sellerKey,signType);
        return verify;

    }
    public static boolean verifySign(String queryString, String sign, String publicKey,String signType) {
        if("md5".equalsIgnoreCase(signType)) {
            String str = DigestUtils.md5Hex(getBytes(queryString));
            log.info("alipay check md5 verifySign query str:" + str + ",sign=" + sign);
            return str.equals(sign);
        }else if("rsa".equalsIgnoreCase(signType)){
            boolean res = RSA.verify(queryString, sign, publicKey, DEFAULT_CHARSET);
            log.info("alipay check rsa  verifySign result:" + res + ",sign=" + sign + ",query str:"+queryString);
            return res;
        }else{
            log.info("alipay check style is  verifySign result:" + signType );
            return true;
        }
    }
    private static String appendPartnerAndCheck(String notifyId, String partner) {
        String str = ALIPAY_GATE_WAY_NOTIFY_VERIFY + "&partner=" + partner + "&notify_id=" + notifyId;
        return requestUrl(str);
    }



    private static String requestUrl(String paramString) {
        String str = "";
        InputStream inputStream = null;
        try {
            log.info("alipay check url:" + paramString);
            URL localURL = new URL(paramString);
            HttpURLConnection httpURLConnection = (HttpURLConnection) localURL.openConnection();
            inputStream = httpURLConnection.getInputStream();
            BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream));
            if(bufferedReader!=null) {
                str = String.valueOf(bufferedReader.readLine());
            }
            log.info("alipay check url return:" + str + ",url" + paramString );
        } catch (Exception e) {
            log.error("",e);
            str = "";
        }finally{
            if(inputStream!=null){
                try {
                    inputStream.close();
                } catch (IOException e) {

                }
            }
        }
        return str;
    }

    public static String request(String strParaFileName, String strFilePath,Map<String, String> sParaTemp,String sellerKey) throws Exception {
        //待请求参数数组
        HttpResult httpResult = HttpClientHelper.sendGet(ALIPAY_GATE_WAY + "_input_charset=" + "utf-8", null, null);
        if (httpResult == null) {
            return null;
        }
        String strResult = httpResult.getResponseString();

        return strResult;
    }



    public static String buildRequestMysign(Map<String, String> sPara,String sellerKey) {
        String prestr = createQueryString(sPara); //把数组所有元素，按照“参数=参数值”的模式用“&”字符拼接成字符串
        return sign(prestr,sellerKey);
    }


    private static Map<String, String> buildRequestPara(Map<String, String> sParaTemp,String sellerKey) {
        //除去数组中的空值和签名参数
        Map<String, String> sPara = paramFilter(sParaTemp);
        //生成签名结果
        String mysign = buildRequestMysign(sPara,sellerKey);

        //签名结果与签名方式加入请求提交参数组中
        sPara.put("sign", mysign);
        sPara.put("sign_type","MD5");

        return sPara;
    }

    public static void main(String[] args) throws UnsupportedEncodingException {
//        String alipayString="sign=7eea3620b7aa8f5529aec44fe3ee49ca&sign_type=MD5&body=(2015041510241309400100099004)&buyer_email=1141900380@qq.com&buyer_id=2088602072280191&discount=0.00&gmt_create=2015-04-15 10:46:20&gmt_payment=2015-04-15 10:46:36&is_total_fee_adjust=N&notify_id=7b990157940ae3f06fc2592e4b94dee132&notify_time=2015-04-15 11:00:09&notify_type=trade_status_sync&out_trade_no=2015041510241309400100099004&payment_type=1&price=0.01&quantity=1&seller_email=finance@dawanju.com&seller_id=2088611921450410&subject=2014款卡宴美规前置四驱3.6L汽油5座&total_fee=0.01&trade_no=2015041500001000190049749455&trade_status=TRADE_SUCCESS&use_coupon=N";
//        String[] p = alipayString.split("&");
//        Map<String,String> param = new HashMap<String,String>();
//        for(String s:p){
//          String[] par =  s.split("=");
//            param.put(par[0],par[1]);
//        }
        String param="body=茅炉充值226&buyer_email=hwp_163@163.com&buyer_id=2088702971218494&discount=0.00&gmt_create=2016-07-06 20:10:52&gmt_payment=2016-07-06 20:10:52&is_total_fee_adjust=N&notify_id=cc4cefb47fde283114adabe542c969ajs6&notify_time=2016-07-06 20:10:53&notify_type=trade_status_sync&out_trade_no=20160706201043140001&payment_type=1&price=0.01&quantity=1&seller_email=tech@morelook.cn&seller_id=2088421263798015&subject=茅炉充值&total_fee=0.01&trade_no=2016070621001004490232044834&trade_status=TRADE_SUCCESS&use_coupon=N";
        //String param="body=${symbol_escape}"茅炉充值225${symbol_escape}"&buyer_email=${symbol_escape}"hwp_163@163.com${symbol_escape}"&buyer_id=${symbol_escape}"2088702971218494${symbol_escape}"&discount=${symbol_escape}"0.00${symbol_escape}"&gmt_create=${symbol_escape}"2016-07-06 18:07:34${symbol_escape}"&gmt_payment=${symbol_escape}"2016-07-06 18:07:34${symbol_escape}"&is_total_fee_adjust=${symbol_escape}"N${symbol_escape}"&notify_id=${symbol_escape}"6c68518f1d2b499465cacf0b3468addjs6${symbol_escape}"&notify_time=${symbol_escape}"2016-07-06 18:07:35${symbol_escape}"&notify_type=${symbol_escape}"trade_status_sync${symbol_escape}"&out_trade_no=${symbol_escape}"20160706180726284001${symbol_escape}"&payment_type=${symbol_escape}"1${symbol_escape}"&price=${symbol_escape}"0.01${symbol_escape}"&quantity=${symbol_escape}"1${symbol_escape}"&seller_email=${symbol_escape}"tech@morelook.cn${symbol_escape}"&seller_id=${symbol_escape}"2088421263798015${symbol_escape}"&subject=${symbol_escape}"茅炉充值${symbol_escape}"&total_fee=${symbol_escape}"0.01${symbol_escape}"&trade_no=${symbol_escape}"2016070621001004490228986751${symbol_escape}"&trade_status=${symbol_escape}"TRADE_SUCCESS${symbol_escape}"&use_coupon=${symbol_escape}"N${symbol_escape}"";
        String sign = "Na5VRmtFDJWxrLpzPQj++LrJmB6v0/qREIuS3FM4XOM6OWqdzjIWIyLhtRvmGUDIlwdDF22EoHrRG6BSxeXEvenk9LpOwc6rKsi3uDn4rKxdbq8UjzK/htQ9aJKj03Rmqf2QkeOXp69J7NzCLYOYKZh362lQoOhECbeW+Fzd8Ec=";
        String key="MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCnxj/9qwVfgoUh/y2W89L6BkRAFljhNhgPdyPuBV64bfQNN1PjbCzkIM6qRdKBoLPXmKKMiFYnkd6rAoprih3/PrQEB/VsW8OoM8fxn67UDYuyBTqA23MML9q1+ilIZwBC2AQ2UBVOrFXfFl75p6/B5KsiNG9zpgmLCUYuLkxpLQIDAQAB";
//        String key="MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDzef3coPaU52SpSOPvD3L/CJ2K${symbol_escape}n" +
//                "fs2oNT6CrK2L/6u1B+qL7jZyp29SsPT02e0wI2WhnQzRf30/+qhpt+eZUGoPuYD5${symbol_escape}n" +
//                "UZBg+cfn+mLm3SKVZhNgzooUpCR4Syzek/FNNBlTykRSImd8JSXl+aWoKx07AdwL${symbol_escape}n" +
//                "1j6Alw9yadzieXfqvwIDAQAB";
        boolean res = RSA.verify(param,(sign),key, "UTF-8");
        System.out.println(res);
    }

}

